//
//  Problem38.swift
//  TestProject 38. 外观数列
//
//  Created by 武侠 on 2020/8/25.
//  Copyright © 2020 zhulong. All rights reserved.
//

import UIKit

/*
 给定一个正整数 n（1 ≤ n ≤ 30），输出外观数列的第 n 项。
 注意：整数序列中的每一项将表示为一个字符串。
 「外观数列」是一个整数序列，从数字 1 开始，序列中的每一项都是对前一项的描述。前五项如下：
 1.     1
 2.     11
 3.     21
 4.     1211
 5.     111221
 第一项是数字 1

 描述前一项，这个数是 1 即 “一个 1 ”，记作 11
 描述前一项，这个数是 11 即 “两个 1 ” ，记作 21
 描述前一项，这个数是 21 即 “一个 2 一个 1 ” ，记作 1211
 描述前一项，这个数是 1211 即 “一个 1 一个 2 两个 1 ” ，记作 111221

 示例 1:
 输入: 1
 输出: "1"
 解释：这是一个基本样例。
 
 示例 2:
 输入: 4
 输出: "1211"
 解释：当 n = 3 时，序列是 "21"，其中我们有 "2" 和 "1" 两组，"2" 可以读作 "12"，也就是出现频次 = 1 而 值 = 2；类似 "1" 可以读作 "11"。所以答案是 "12" 和 "11" 组合在一起，也就是 "1211"。
 */
@objcMembers class Problem38: NSObject {
    func solution() {       // 312211
        let list = [1, 2, 3, 4, 5]
        for item in list {
            print("item = ", item, countAndSay(item))
        }
        
       
    }
    func countAndSay(_ n: Int) -> String {
        if n == 1 {
            return "1"
        }
        
        var i = 0
        var num:String = "1"
        while i < n - 1 {
            num = countStrNext(num)
            i += 1
        }
        return String(num)
    }
    
    // 实现了：获取数字n的第n个值：
    func countAndSayN(_ n: Int) -> String {
        if n == 1 {
            return "1"
        }
        
        var i = 0
        var num = n
        while i < n {
            num = Int(countNext(num)) ?? 0
            i += 1
        }
        return String(num)
    }
    
    func countNext(_ n: Int) -> String {
        var str = ""
        var num = n
        var t = -1
        var l = 0
        while num > 0 {
            let s = num % 10
            if t == -1 {
                t = s
                l = 1
            } else {
                if t == s {
                    l += 1
                } else {
                    str = String(l) + String(t) + str
                    l = 1
                    t = s
                }
            }
            num /= 10
        }
        
        if t != -1 {
            str = String(l) + String(t) + str
        }
        
        return str
    }
    
    func countStrNext(_ n: String) -> String {
        var str = ""
        var t:Character = "-"
        var l = 0
        var end = n.endIndex
        while end != n.startIndex {
            let s = n[n.index(before: end)]
            if t == "-" {
                t = s
                l = 1
            } else {
                if t == s {
                    l += 1
                } else {
                    str = String(l) + String(t) + str
                    l = 1
                    t = s
                }
            }
            end = n.index(before: end)
        }
        
        if t != "-" {
            str = String(l) + String(t) + str
        }
        
        return str
    }
}
